#pragma once
#include <openssl/ssl.h>
#include <memory>
#include <muduo/base/noncopyable.h>
#include <muduo/net/TcpConnection.h>
#include <muduo/net/Buffer.h>
#include "SSLContext.hpp"


// 应用层明文 ⇄ [SSL filter BIO] ⇄ [socket BIO] ⇄ 网络字节流
// 你调 BIO_write(ssl_bio, plain, len) → 经过 BIO_f_ssl() 被加密 → 再经过 BIO_s_socket() 发到 TCP。
// 反之，TCP 收到密文 → BIO_read(socket_bio) → 经过 BIO_f_ssl() 被解密 → 你拿到明文
namespace ssl
{
    // 定义消息回调函数类型
    using MessageCallback = std::function<void(const std::shared_ptr<muduo::net::TcpConnection> &,
                                               muduo::net::Buffer *, muduo::Timestamp)>;

    class SSLConnection : muduo::noncopyable // 继承自noncopyable类，防止拷贝构造和赋值运算符
    {
    private:
        void handleHandshake();
        void onEncrypt(const char *data, size_t len);
        void onDecrypt(const char *data, size_t len);
        SSLErrorType getLastError(int ret) const;
        void handleError(SSLErrorType error);

    public:
        using TcpConnectionPtr = std::shared_ptr<muduo::net::TcpConnection>;
        using BufferPtr = muduo::net::Buffer *;

        SSLConnection(const TcpConnectionPtr &connection, SSLContext *context);
        ~SSLConnection();

        void startHandshake();
        void send(const void *data, size_t len);
        void onRead(const TcpConnectionPtr &conn, BufferPtr buf, muduo::Timestamp time);
        bool isHandshakeComplete() const { return _state == SSLState::ESTABLISHED; };
        muduo::net::Buffer *getDecryptBuffer() { return &_decryptBuffer; };

        // SSL BIO操作
        static int bioRead(BIO *bio, void *data, size_t len);
        static int bioWrite(BIO *bio, const void *data, size_t len);
        static long bioCtrl(BIO *bio, int cmd, long num, void *ptr);

        void setMessageCallback(const MessageCallback &cb) { _messageCallback = cb; };

    private:
        SSL *_ssl;                         // SSL结构体指针
        SSLContext *_context;              // SSL上下文指针
        TcpConnectionPtr _connection;      // TCP连接指针
        SSLState _state;                   // SSL状态
        BIO *_readBio;                     // 读取BIO指针 网络数据->SSL数据
        BIO *_writeBio;                    // 写入BIO指针 SSL数据->网络数据
        muduo::net::Buffer _readBuffer;    // 读取缓冲区
        muduo::net::Buffer _writeBuffer;   // 写入缓冲区
        muduo::net::Buffer _decryptBuffer; // 解密缓冲区
        MessageCallback _messageCallback;  // 消息回调函数
    };
}